/*
    Contact info:
    bhepple@freeshell.org
    http://bhepple.freeshell.org/scrmgr

    Copyright (C) 1991-2008 Bob Hepple

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/
/*

Screen Manager Library - main include file.

When adding items to the screen definition file remember:

1. Add the item to the screen file smcreate.dat
2. Add item to structure definition.
3. Increase the SM_NUMBER_OF_SOMETHING_FIELDS
4. Change constructors and destructors
5. Add #define for the item (SM_SOMETHING_F)
6. Add entry in smlib2.c to write the field
7. Next time the .dat file is written, it should contain the new item.

*/

/* This needs to be up here so that the mylib.h includes are asserted 
   properly */

#ifdef SM_DEBUG
#undef NDEBUG
#else
#define NDEBUG 1
#endif

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <values.h>
#include <sys/param.h>
#include <mylib.h>
#include <assert.h>

#ifndef SMLIB
#define SMLIB

#ifndef SM_CLASS
#define SM_CLASS
#endif

#define ENH			int
#define FTYPE			int
#define COMMAND			int
#define SM_MAX_POPUP		10	/* Maximum number of windows */
#define SM_BASE_WINDOW		0
#define GETCWD(x,y)		getcwd((x),(y)) /* except bsd4.2 & SunOS */

/* Character used to mark fields for editing & exporting */
#define SM_SCREEN_CHAR 		'#'

#define SM_MaxPromptLen 67

#define SM_LASTCHAR(p) (*p? (strchr((p),0) - 1): p)

#define SM_ASSIGN(x, y)		(x)=sm_assign((x),(y), 0)
#define SM_FASSIGN(x, y, z)	(x)=sm_assign((x),(y),(z))

/*************************************************************/
/* All machine dependent defines go here		     */
/*************************************************************/

/* Check that at least one machine is defined */
/*
#ifndef SM_TURBOC
#ifndef SM_XENIX
#ifndef SM_SUNOS
#ifndef SM_SGI
#ifndef SM_SYSV
	whoops
#endif
#endif
#endif
#endif
#endif
*/

/**************************************************/
/*** MS-DOS compiled by Turbo-C 2.0 ***************/
/**************************************************/

#ifdef SM_TURBOC
#if defined(SM_XENIX) || defined(SM_SUNOS) || defined(SM_SGI) || defined(SM_SYSV)
	whoops
#endif
#define MAXPATHLEN 		128
#define MAXNAMELEN 		12
#define TC_NDIR			1
#define IBM_LINE_DRAWING	1
#define USE_COMMAND		1
#define ROOT_IS_A_REGULAR_FILE	1
#define USE_DRIVE_LETTER	1
#define SM_MOUSE		1
#define NUM_FKEYS		12
#define NO_SYS_NERR		1 /* really weird - it's not in errno.h!! */
#define NEEDS_PATH_FOR_PROGS	1
#define USE_SCRMGR_PROGS	1 /* smedit/smmore/$PAGER instead of vi/more/man */
#define HAS_NO_MAN		1 /* No man(1) subsystem - use PAGER */
#define NEWLINE_PLUS_CR		1
#define SLOW_READ_BACKWARDS	1
#define CANT_PIPE		1
#define BACKSLASH_AND_SLASH	1
#define HAS_GETHOSTNAME		0
#define READ_DAT_AT_RUNTIME	0
#define USE_SETFTIME		1
#define IS_SECURE		1
#define NO_STRPTIME		1
#define NO_TIMEGM		1
#define SYSTEM_CANT_REDIRECT	1
#ifndef SM_MAXREC
#define SM_MAXREC 		1024
#endif
#endif /* SM_TURBOC */

/**************************************************/
/*** SCO Xenix 386 2.3.3 **************************/
/**************************************************/

#ifdef SM_XENIX
#if defined(SM_TURBOC) || defined(SM_SUNOS) || defined(SM_SGI) || defined(SM_SYSV) || defined(SM_SUNVIEW)
	whoops
#endif
#define MAXPATHLEN 		255
#define MAXNAMELEN 		14
#define XENIX_NDIR		1
#undef  SM_MOUSE
#define NUM_FKEYS		8
#define HAS_UNAME		1
#define HAS_GETHOSTNAME		0
#endif

/**************************************************/
/*** SunOS under System V curses ******************/
/**************************************************/

#ifdef SM_SUNOS
#if defined(SM_TURBOC) || defined(SM_XENIX) || defined(SM_SGI) || defined(SM_SYSV) || defined(SM_SUNVIEW)
	whoops
#endif
#define MAXPATHLEN 		1023
#define MAXNAMELEN 		255
#define BSD_DIRENT		1
#define SM_MOUSE		1
#define HAS_XCTOOL		1
#define NUM_FKEYS		8
#define NO_SYS_NERR		1 /* really weird - it's not in errno.h!! */
#undef GETCWD
#define GETCWD(x,y)		getwd(x)
#define HAS_UNAME		0
#define HAS_GETHOSTNAME		1
#define IS_SECURE		1
#endif

/**************************************************/
/*** SunOS under SUNVIEW (unfinished)**************/
/**************************************************/

#ifdef SM_SUNVIEW
#if defined(SM_TURBOC) || defined(SM_XENIX) || defined(SM_SGI) || defined(SM_SYSV) || defined(SM_SUNOS)
	whoops
#endif
#define MAXPATHLEN 		1023
#define MAXNAMELEN 		255
#define SUNOS_DIRENT		1
#define SM_MOUSE			1
#define NUM_FKEYS		8
#undef GETCWD
#define GETCWD(x,y)		getwd(x)
#define HAS_UNAME		0
#define HAS_GETHOSTNAME		1
#define IS_SECURE		1
#endif

/**************************************************/
/*** Silicon Graphics under 4Sight ****************/
/**************************************************/

#ifdef SM_SGI
#if defined(SM_TURBOC) || defined(SM_XENIX) || defined(SM_SUNOS) || defined(SM_SYSV) || defined(SM_SUNVIEW)
	whoops
#endif
#define MAXPATHLEN 		1023
#define MAXNAMELEN 		255
#define UNSIGNED_CHAR 		1
#define SYSV_DIRENT		1
#undef  SM_MOUSE
#define NUM_FKEYS		12
#define HAS_UNAME		1
#define HAS_GETHOSTNAME		1
#endif

/**************************************************/
/*** Generic System V incl. Linux *****************/
/**************************************************/

#ifdef SM_SYSV
#if defined(SM_TURBOC) || defined(SM_XENIX) || defined(SM_SUNOS) || defined(SM_SGI) || defined(SM_SUNVIEW)
	whoops
#endif
#include <sys/param.h> /* For MAXPATHLEN */
#define MAXNAMELEN 		256
#define NO_SYS_NERR		1 /* use strerror instead of sys_errlist etc */
#define SYSV_DIRENT		1
#define SM_MOUSE		1
#define NUM_FKEYS		8
#define HAS_UNAME		1 /* as opposed to HAS_GETHOSTNAME */
#define GETCWD_IS_DECLARED	1 /* declared in /usr/include/??? */
#undef  IS_SECURE
#undef  NO_STRPTIME
#define NO_TIMEGM		1
#endif

/********************************/
/* End of system-specific stuff */
/********************************/

#ifdef HAS_NO_VOID
#define void int /* strewth! */
#endif

#ifndef SM_MAXREC
#define SM_MAXREC 1024 		/* ... maximum record/field size - can be
				   overridden at compile-time */
#endif

#if UNSIGNED_CHAR
#define CHAR			unsigned char
#else
#define CHAR			char
#endif

#ifndef GETCWD_IS_DECLARED
extern char *getcwd HARG2(char *, s, int, len);
#endif

#define  CALLBACK(x) int x  ARG2(int, command, void *, callback_data)
#define HCALLBACK(x) int x HARG2(int, command, void *, callback_data)

/* Attributes */
#define SM_HIDDEN		1
#define SM_VISIBLE		0
#define SM_PROT			1
#define SM_UNPROT		0
#define SM_NOT_TOGGLE		-1

/* Enhancements */

#define SM_NORMAL		0
#define SM_INVERSE		1
#define SM_STANDOUT		2
#define SM_BLINK		4
#define SM_UNDER		8
#define SM_BOLD			16
#define SM_DRAW			32

/* Field Types - add 100 to enforce non-zero/non-blank */

#define SM_ALPHANUM_FT		0
#define SM_INTEGER_FT		1
#define SM_FLOAT_FT		2
#define SM_FIXED_FT		3
#define SM_BINARY_FT		4
#define SM_OCTAL_FT		5
#define SM_HEX_FT		6
#define SM_LETTERS_FT		7
#define SM_IDATE_FT		8	/* International date */
#define SM_ADATE_FT		9	/* American date */
#define SM_TIME_FT		10
#define SM_BOOL_FT		11	/* 0 or 1, presented as Y or N */
#define SM_FIELD_FT		12
#define SM_FILE_FT		13
#define SM_TIMESTAMP_FT		14
#define SM_DIR_FT		15

/* Mouse definitions */
#define SM_MOUSE_LEFT		1
#define SM_MOUSE_MIDDLE		2
#define SM_MOUSE_RIGHT		4
#define SM_MOUSE_SHIFT		8
#define SM_MOUSE_CONTROL	16
#define SM_MOUSE_META		32
#define SM_MOUSE_DOUBLE		64
#define SM_MOUSE_UP		128

/* Input key names */
#define SM_LEFT_K		0400
#define SM_RIGHT_K		0401
#define SM_UP_K			0402
#define SM_DOWN_K		0403
#define SM_PGUP_K		0404
#define SM_PGDN_K		0405
#define SM_HOME_K		0406
#define SM_END_K		0407
#define SM_INS_K		0410
#define SM_DEL_K		0411
#define SM_F1_K			0412
#define SM_F2_K			0413
#define SM_F3_K			0414
#define SM_F4_K			0415
#define SM_F5_K			0416
#define SM_F6_K			0417
#define SM_F7_K			0420
#define SM_F8_K			0421
#define SM_F9_K			0422
#define SM_F10_K		0423
#define SM_F11_K		0424
#define SM_F12_K		0425
#define SM_TAB_K		0426
#define SM_ENTER_K		0427
#define SM_RET_K		0430
#define SM_BS_K			0431
#define SM_ESC_K		0432	
#define SM_CLEAR_EOL_K		0433	
#define SM_CLEAR_EOS_K		0434	
#define SM_MOUSE_EVENT_K	0435
#define SM_RIGHT_WORD_K		0436
#define SM_LEFT_WORD_K		0437
#define SM_HOME_SCREEN_K	0440
#define SM_END_SCREEN_K		0441
#define SM_FIRST_SCREEN_K	0442
#define SM_LAST_SCREEN_K	0443
#define SM_STAB_K		0444

/* Commands ... 0500-0600 if you add a command, add it to the command table in
   smlib.c too! */

#define SM_LEFT_C		0500
#define SM_RIGHT_C		0501
#define SM_TOGGLE_INS_C		0502
#define SM_DEL_CHAR_C		0503
#define SM_DEL_BACK_C		0504
#define SM_NEXT_FIELD_C		0505
#define SM_NEXT_LINE_C		0506
#define SM_PREV_FIELD_C		0507
#define SM_HOME_FIELD_C		0510
#define SM_END_FIELD_C		0511
#define SM_CLEAR_FIELD_C	0512
#define SM_TRANSPOSE_CHARS_C	0513
#define SM_COPY_FIELD_C		0514
#define SM_YANK_FIELD_C		0515
#define SM_DELETE_FIELD_C	0516

#define SM_TOGGLE_CASE_C	0517
#define SM_LEFT_WORD_C		0520
#define SM_RIGHT_WORD_C		0521 
#define SM_DEL_WORD_C		0522
#define SM_DEL_WORD_BACK_C	0523
#define SM_TRANSPOSE_WORDS_C	0524

#define SM_HOME_SCREEN_C	0525
#define SM_END_SCREEN_C		0526
#define SM_CLEAR_SCREEN_C	0527
#define SM_NEXT_SCREEN_C	0530
#define SM_PREV_SCREEN_C	0531
#define SM_FIRST_SCREEN_C	0532
#define SM_LAST_SCREEN_C	0533
#define SM_SELECT_SCREEN_C	0534
#define SM_INSERT_DATA_C	0535
#define SM_DELETE_DATA_C	0536
#define SM_SPLIT_LINE_C		0550
#define SM_JOIN_LINES_C		0551
#define SM_YANK_DATA_C		0552
#define SM_COPY_DATA_C		0553
#define SM_MOUSE_EVENT_C	0554
#define SM_CHANGE_TYPE_C	0555
#define SM_SHELL_OUT_C		0556
#define SM_QUIT_C		0557
#define SM_REFRESH_C		0560
#define SM_UP_C			0561
#define SM_DOWN_C		0562
#define SM_EDIT_MASTER_C	0563
#define SM_POPUP_C		0564
#define SM_HELP_C		0565
#define SM_KEY_LISTS_C		0566
#define SM_KEY_HELP_C		0567
#define SM_CALLBACK_FN_C	0570       
#define SM_LOAD_FILE_C		0571
#define SM_STORE_FILE_C		0572
#define SM_STORE_FILE_AS_C	0573
#define SM_CLEAR_FILE_C		0574
#define SM_EXIT_C		0575
#define SM_NO_SAVE_EXIT_C	0576
#define SM_REPAINT_C		0577
#define SM_YES_C		0600
#define SM_NO_C			0601
#define SM_CANCEL_C		0602
#define SM_GOTO_RECORD_C	0603
#define SM_IGNORE_CASE_C	0604
#define SM_SEARCH_REP_C		0605
#define SM_SEARCH_C		0606
#define SM_REPLACE_ALL_C	0607
#define SM_AGAIN_C		0610
#define SM_SEARCH_BACKWARDS_C	0611
#define SM_WHERE_C		0612
#define SM_NEXT_KEYS_C		0613
#define SM_SORT_C		0614
#define SM_WHERE_CONFIRM_C	0615
#define SM_WHERE_SKIP_C		0616
#define SM_WHERE_DO_ALL_C	0617
#define SM_TELL_VERSION_C	0620
#define SM_HELP_MANUAL_C	0621
#define SM_SCRMGR_MANUAL_C	0622
#define SM_EXEC_PROG_C		0623
#define SM_EXEC_PROG_NO_ERR_C	0624
#define SM_POPUP_MENU_C		0625

/* non-commands ... */
#define SM_NOT_A_CALLBACK	0676
#define SM_POPCALLBACK		0677
#define SM_MAX_COMMAND		0677 /* Boundary */

/* Keyword values */
#define SM_NAME_F		0    
#define SM_SCROLLING_F		1      
#define SM_ROW_F		2	     
#define SM_COL_F		3	     
#define SM_ATTRIBUTE_F		4      
#define SM_HIDDEN_F		5	  
#define SM_PROTECT_F		6	 
#define SM_FTYPE_F		7	   
#define SM_LEN_F		8	     
#define SM_MAXLEN_F		9	   
#define SM_C_DEFAULT_F		10     
#define SM_KEYSCREEN_F		11
#define SM_TEXT_F		13
#define SM_KEY_NUM_F		14
#define SM_UPPER_F		15
#define SM_LOWER_F		16
#define SM_KEY_NAME_F		17
#define SM_TOGGLE_F		18
#define SM_KEY_HELP_F		19
#define SM_CALLBACK_FN_F	20
#define SM_SCR_TABLE_F		21
#define SM_FLD_TABLE_F		22
#define SM_BG_TABLE_F		23
#define SM_SKEY_TABLE_F		24
#define SM_FIELD_F		25
#define SM_SCREEN_F		26	
#define SM_BG_F			28	
#define SM_KEY_F		29
#define SM_SCREEN_FIELDNAMES_F	30
#define SM_FIRST_FIELD_F	31
#define SM_NEXT_FIELD_F		32
#define SM_FILE_TABLE_F		33
#define SM_TAG_F		34
#define SM_SEPARATOR_F		35
#define SM_FILE_F		36
#define SM_SORT_FIELD_F		37
#define SM_SORT_REVERSE_F	38
#define SM_SORT_IGNORE_CASE_F	39
#define SM_SORT_MONTH_F		40  
#define SM_SORT_NUMERIC_F	41
#define SM_CONSTANT_START_F	42
#define SM_CONSTANT_END_F	43
#define SM_FILENAME_F		44
#define SM_TEMP_STORAGE_F	45
#define SM_MENU_F		46
#define SM_MENU_TABLE_F		47
#define SM_MENU_TYPE_F		48
#define SM_MENU_TEXT_F		49
#define SM_MENU_COMMAND_F	50
#define SM_TRIGGER_FN_F		51
#define SM_ASCENDING_F		52 /* obsolete */
#define SM_SORT_KEY_F		53 /* obsolete */
#define SM_IGNORE_CASE_F	54 /* obsolete */
#define SM_SCREEN_SOFTKEY_F	55
#define SM_AUTO_ADJUST_F	56
#define SM_ERROR		-1

#define SM_CTRL(x)		((x) & 037)
#define SM_META(x)		((x) | 01000)

#define SM_BUILTIN_SCREENS	0
#define SM_SCRMGR_SCREENS	1
#define SM_USER_SCREENS		2
#define SM_EXTRA_SCREENS	3

/* Fundamental data structure for holding data. The array of pointers,
 * terminated with a NULL pointer */
typedef CHAR **SM_DATA;

/* Base data structures for holding screen, field, skey etc definitions.
   If something is added, then remember to accomodate the change in the 
   reading routines and, separately, in the writing routines, as well as
   in the .dat files themselves.

   In general, there is are creator and destructor routines for each base
   type.
*/

/* Field stuff */
struct sm_field {
    CHAR		*field_name;
    int			row;
    int			col;
    int			attribute;
    int			hidden;
    int			protect;
    int			ftype;
    int			non_blank;
    int			has_popup;
    int			disallow_chdir; /* file/dir ftype only */
    int			disallow_insert; /* non-file/dir ftype only */
    int			len; /* = length displayed on screen */
    int			max_len;
    int			changed; /* since setup or enquired */
    CHAR		*trigger_fn;
    CHAR		*next_field;
    ARRAY		pop_up;

    /* Values for character fields */
    CHAR		*c_value;
    CHAR		*c_default;

    /* Link to key item in master file */
    CHAR		*master_screen_name;
    struct sm_screen_s	*master_screen;
    struct sm_field	*master_fieldp;

    /* Linkages */
    struct sm_screen_s	*parent;
#ifdef SM_XVIEW
    void		*xv_ptr;
#endif
#ifdef SM_XAW
    void		*xaw_widgetp; /* Actually (Widget *) */
#endif
};
typedef struct sm_field *SM_FIELD;
#define SM_NUM_FLD_FIELDS 13
    
struct sm_background {
    STRING		text;
    int			row;
    struct sm_screen_s	*parent;
};
typedef struct sm_background *SM_BACKGROUND;
#define SM_NUM_BG_FIELDS 2

struct sm_sortkey {
    CHAR		*sortfield_name;
    SM_FIELD		sortfield;
    int			reverse;
    int			ignore_case;
    int			month;
    int			numeric;
    struct sm_screen_s	*parent;
};
typedef struct sm_sortkey *SM_SORTKEY;

struct sm_temp_file_s {
    FILE		*file;
    INDEX		index;
    INDEX		offset;
    INDEX		size;
    CHAR		*fileName;
    CHAR		*currentRecord;
};
typedef struct sm_temp_file_s *SM_TEMP_FILE;

struct sm_screen_s {
    CHAR		*screen_name;
    int			changed;
    CHAR		*filename;
    ARRAY		data_field;	/* Defines the order of fields in the 
					   physical record */
    CHAR		*first_field;
    CHAR		*softkey;
    struct sm_skey	*skey;
    int			auto_adjust;

    /* These are used in scrolling screens */
    int			scrolling;
    CHAR		*constant_start;
    CHAR		*constant_end;
    int			current_line;
    INDEX		current_rec;

    /* These are used in smdb ... */
    CHAR		temp_storage;  	/*  - M(emory), F(ile) or R(db) */
    int			dirty_file;	/* flag */
    INDEX		num_records;
    ARRAY		data;		/* if using memory temp storage */
    INDEX		index;
    SM_TEMP_FILE	lower, upper;	/* These used for F(ile) */
    
    /* Linkages */

    ARRAY		background;	/* All the screen's text */
    ARRAY		field;		/* All the screen's fields */
    ARRAY		sortkey;
    struct sm_file_s	*parent;
    SM_FIELD		timestamp_field;
#if SM_XAW
    void		*xaw_form;
#endif    
};
typedef struct sm_screen_s *SM_SCREEN;
#define SM_NUM_SCR_FIELDS 15
    
struct sm_skey {
    CHAR		*skey_name;
    CHAR		*upper[8];
    CHAR		*lower[8];
    CHAR		*key_name[8];
    CHAR		*key_help[8];
    CHAR		*key_argument[8];
    struct sm_file_s	*parent;
    int			toggle[8]; /* tri-state (SM_NOT_TOGGLE, TRUE, FALSE) */
};
typedef struct sm_skey *SM_SOFTKEY;
#define SM_NUM_SKEY_FIELDS 49
#define SM_NUM_FIELDS_PER_SKEY 6

struct sm_menu_item {
    CHAR	*text;
    CHAR	*command;
    int		start; /* for bar menu only */
    int		key;
};
typedef struct sm_menu_item *SM_MENU_ITEM;

struct sm_menu {
    CHAR		*menu_name;
    int			type; /* 1=bar 0=pull-down */
    ARRAY		items; /* of SM_MENU_ITEM */
    struct sm_file_s	*parent;
};
typedef struct sm_menu *SM_MENU;
#define SM_NUM_MENU_FIELDS 4

struct sm_keyword_s {
    CHAR		*string;
    int			value;
    CHAR		*help;
    f_ptr		argument;
    ARRAY		parent;
};
typedef struct sm_keyword_s *SM_KEYWORD;

/* Highest structure in the heirarchy */
struct sm_file_s {
    CHAR		*tagname;
    CHAR		separator;
    int			untabify;
    ARRAY		scr;
    ARRAY		skey;
    ARRAY		menu;
};
typedef struct sm_file_s *SM_FILE;
#define SM_NUM_FILE_FIELDS 2
#define SM_NUM_STRUCTURES 4

/* This is here so that it can be shared between smedit & smwhere ... */
struct edit_s {
    f_ptr	destructor;
    CHAR 	static_part[SM_MAXREC];
    SM_FIELD	current_field;
    SM_SCREEN	current_screen;
    SM_SCREEN	last_tagged_screen, /* Only for tagged screens */
    		base_screen;	/* Screen for data etc - may be
				   different to 'current_screen' for tagged 
				   files or for keyed files */
    int		base_screen_has_masters;
    INDEX    	first_data_on_screen;
    INDEX	last_data_on_screen;
    CHAR	*yank;
    f_ptr	lambda;
    int		gedout;
    int		window;
    INDEX	old_index;
    int		command;
    SM_SOFTKEY	old_skey;
    FILE	*f;
    int		last_op;
    SM_SOFTKEY	set_in_use;
    int		where_action;
    INDEX	start_rec, end_rec;
    int		temp_sep;
    int		target_col;
    SM_SCREEN	target_for_field_popups;
    int		can_go_up;
};

				/* Naughty global variables */

extern ARRAY		sm_keyword,
    			sm_command_table;

extern int		sm_use_menus;

extern CHAR		sm_version[],
    			sm_mem_error[],
			sm_msg[],
		       *sm_buf,
			sm_default_separator,
    		        sm_program_name[],
		        sm_program_directory[];

extern SM_FIELD  	sm_prompt_fld,
	  		sm_dumb_fld;

extern SM_SOFTKEY	smio_current_skey;

/* These are from smbuilt.dat - if you include them you can't compile
   sm2c - therefore hardcode and maintain manually! */
SM_CLASS SM_SCREEN  sm_prompt_scr, sm_dumb_scr, sm_where_scr, sm_help_scr;
SM_CLASS SM_SOFTKEY  sm_getfilename_skey, sm_save_exit_skey, sm_confirm_skey, sm_prompt_skey, sm_key_help_skey, sm_help_skey, sm_data_skey, sm_third_data_skey, sm_second_data_skey, sm_sort_skey, sm_where_exec_skey, sm_where_skey, sm_selection_skey;

extern int		sm_wr_num_file_fields,
			sm_rd_num_file_fields,
		       *sm_rd_file_line_order,
			sm_wr_file_line_order[],

			sm_wr_num_fld_fields,
			sm_rd_num_fld_fields,
		       *sm_rd_fld_line_order,
			sm_wr_fld_line_order[],

			sm_wr_num_bg_fields,
			sm_rd_num_bg_fields,
		       *sm_rd_bg_line_order,
			sm_wr_bg_line_order[],

			sm_wr_num_scr_fields,
			sm_rd_num_scr_fields,
		       *sm_rd_scr_line_order,
			sm_wr_scr_line_order[],

			sm_wr_num_menu_fields,
			sm_rd_num_menu_fields,
		       *sm_rd_menu_line_order,
			sm_wr_menu_line_order[],

			sm_wr_num_skey_fields,
			sm_rd_num_skey_fields,
		       *sm_rd_skey_line_order,
			sm_wr_skey_line_order[];

SM_FILE 		sm_user_screens();
SM_FILE 		sm_extra_screens();
SM_FILE 		sm_builtin_screens();
SM_FILE 		sm_scrmgr_screens();

void 		sm_pre_init 	HARG2(int, argc, CHAR **, argv);

void 		sm_init		HARG3(int, 		doit,
				      int,		argc,
				      CHAR **,		argv);

void 		sm_enq_term 	HARG3(int,		window,
				      int *, 		row,
				      int *, 		col);

int 		sm_enq_mouse 	HARG3(int *, 		row, 
				      int *, 		col, 
				      int *, delta);

int 		sm_anything_there HARG1(SM_FILE, 	screenset);

SM_KEYWORD	*sm_destroy_keyword 
    				HARG1(SM_KEYWORD *, 	kp);

void 		sm_destroy_all_keywords 
				HARG1(ARRAY,	 	table);

void		sm_clear_out 	HARG1(int,		clear_all);

void		_sm_clear_out 	HARG1(int,		i);

void		sm_term 	NOARGS;

int	 	sm_lookup_keyword 	
				 HARG2(ARRAY,	 	table, 
				       CHAR *, 		line);

CHAR	 	*sm_lookup_string HARG2(ARRAY,	 	table, 
					int,		value);

CHAR	 	*sm_lookup_help	 HARG2(ARRAY,	 	table, 
				       int,		value);

/*
 *
 * File and data block opening
 *
 */

SM_FIELD	sm_read_fld 	HARG3(SM_SCREEN, 	screen,
				      SM_FIELD, 	field,
				      CHAR *, 		line);

void		sm_read_gbl 	HARG2(SM_FILE,		screenset,
				      CHAR *, 		line);

SM_SCREEN	sm_read_scr 	HARG3(SM_FILE,		screenset,
				      SM_SCREEN, 	screen,
				      CHAR *, 		line);

SM_MENU		sm_read_menu 	HARG2(SM_FILE,		screenset,
				      CHAR *, 		line);

SM_BACKGROUND	sm_read_bg 	HARG3(SM_SCREEN, 	screen,
				      SM_BACKGROUND, 	bg,
				      CHAR *, 		line);

SM_SOFTKEY	sm_read_skey 	HARG3(SM_FILE,		screenset,
				      SM_SOFTKEY, 	key,
				      CHAR *, 		line);

int		sm_fopen 	HARG2(SM_FILE,		screenset,
				      CHAR *, 		file_name);

int		sm_dbopen 	HARG2(SM_FILE,		screenset,
				      CHAR **, 		data_block);

/*
 *
 * Write screen file - writes all screens & labels currently stored.
 *
 */

CHAR *		sm_format_file 	HARG2(SM_FILE,		screenset,
				      CHAR *, 		buf);

CHAR *		sm_format_scr 	HARG3(SM_SCREEN, 	screen,
				      CHAR *, 		buf,
				      SM_SORTKEY,	sortkey);

CHAR *		sm_format_fld 	HARG2(SM_FIELD, 	field,
				      CHAR *, 		buf);

CHAR *		sm_format_bg 	HARG2(SM_BACKGROUND, 	bg,
				      CHAR *, 		buf);

CHAR *		sm_format_skey 	HARG2(SM_SOFTKEY, 	skey,
				      CHAR *, 		buf);

CHAR 		*sm_format_menu HARG3(SM_MENU, 		menu,
				      int,		item,
				      CHAR *, 		buf);

int		sm_fwrite 	HARG2(SM_FILE,		screenset,
				      FILE *, 		f);

/*
 *
 * Screen and window control and enquiry
 *
 */

int		sm_popup_win	HARG4(int, 		num_rows,
				      int, 		num_cols,
				      int, 		row,
				      int, 		col);

void		sm_del_win	HARG1(int,		window);

SM_SORTKEY 	*sm_create_sortkey HARG1(SM_SCREEN, 	screen);

SM_SORTKEY	*sm_destroy_sortkey
    				HARG1(SM_SORTKEY *,	sortkey);

void 		sm_destroy_all_sortkeys 
				HARG1(SM_SCREEN, 	screen);

SM_SORTKEY 	*sm_first_sortkey HARG1(SM_SCREEN, 	screen);

SM_SORTKEY	*sm_next_sortkey
    				HARG1(SM_SORTKEY *,	sortkey);

SM_SORTKEY 	sm_open_sortkey HARG2(SM_SCREEN, 	screen, 
				      CHAR *, 		name);

SM_SCREEN	*sm_create_scr 	HARG1(SM_FILE,		screenset);

SM_SCREEN 	*sm_destroy_scr HARG1(SM_SCREEN *, 	screen);

void 		sm_destroy_all_scrs 
				HARG1(SM_FILE, 		screenset);

SM_SCREEN	*sm_first_scr 	HARG1(SM_FILE, 		screenset);

SM_SCREEN	*sm_next_scr 	HARG1(SM_SCREEN *, 	screen);

SM_SCREEN	*sm_prev_scr 	HARG1(SM_SCREEN *, 	screen);

SM_SCREEN	sm_scr_open 	HARG2(SM_FILE, 		screenset,
				      CHAR *, 		screen_name);

void		sm_scr_init 	HARG2(SM_SCREEN, 	screen,
				      int,		recursive);

void		sm_paint_scr 	HARG3(int,		window,
				      SM_SCREEN, 	screen,
				      int,		enhance);

void		sm_null_scr 	HARG1(int,		window);

int		sm_scr_changed 	HARG1(SM_SCREEN, 	screen);

void		sm_set_scr_unchanged 	
				HARG1(SM_SCREEN, 	screen);

void 		sm_set_scr_changed 
				HARG1(SM_SCREEN, 	screen);

void 		sm_update_record_timestamp 
    				HARG1(SM_SCREEN, screen);

int 		sm_check_data_field 
				HARG1(SM_SCREEN, 	screen);

void 		sm_calc_scrolling_line
				HARG1(SM_SCREEN, 	screen);

int		sm_check_screens  
				HARG1(SM_FILE, 	screenset);

SM_SCREEN	sm_choose_scr 	HARG2(SM_FILE, 		screenset,
				      CHAR *, 		line);

int		sm_setup_scr 	HARG7(int,		window,
				      SM_SCREEN, 	screen,
				      SM_FIELD,		init_field,
				      SM_SCREEN,	target_for_popups,
				      int,		return_on_mouse_events,
				      int,		target_col,
				      int,		return_on_SM_UP_C);

int		sm_data_to_screen HARG3(SM_SCREEN, 	screen,
					CHAR *, 	data,
					int,		static_part_only);

void		sm_screen_to_data HARG2(CHAR *, 	data,
					SM_SCREEN, 	screen);

void		sm_rename_scr 	HARG2(SM_SCREEN, 	screen,
				      CHAR *, 		new_name);

void		sm_paint_part_scr HARG3(int,		window,
					SM_SCREEN, 	screen,
					int, 		row);

SM_SCREEN 	sm_current_scr	NOARGS;

int 		sm_setup_edit 	HARG6(int,		window,
				      SM_SCREEN, 	screen,
				      int, 		gedout,
				      f_ptr, 		f,
				      SM_SOFTKEY,	skey,
				      SM_SCREEN,	target_for_field_popups);

int 		sm_calc_sort_params 
				HARG5(SM_SCREEN,	screen,
				      CHAR *,		fieldname,
				      int *,		field_num,
				      int *,		char_start,
				      int *,		char_end);

void		sm_where_close_file 
				HARG1(struct edit_s *, 	edit);

void 		sm_setup_where 	HARG1(struct edit_s *, 	edit);

int		sm_setup_getfilename HARG5(CHAR *, 	filename,
					   CHAR *, 	direct,
					   CHAR *, 	msg,
					   int,		dir_only,
					   int,		disallow_chdir);

void 		sm_getfilename 	HARG2(CHAR *, 		filename,
				      CHAR *, 		direct);

/*
 *
 * Softkey label control and enquiry
 *
 */

SM_SOFTKEY	sm_create_skey	HARG1(SM_FILE,		screenset);

SM_SOFTKEY	*sm_destroy_skey 
				HARG1(SM_SOFTKEY *,	softkey_set);

void 		sm_destroy_all_skeys 
				HARG1(SM_FILE,		screenset);

SM_SOFTKEY	sm_skey_open 	HARG2(SM_FILE,		screenset,
				      CHAR *, 		softkey_name);

void		sm_skey_init 	HARG1(SM_SOFTKEY, 	softkey_set);

void		sm_paint_skey 	HARG1(SM_SOFTKEY, 	softkey_set);

void		sm_null_skey	NOARGS;

CHAR		*sm_skey_name 	HARG2(SM_SOFTKEY, 	softkey_set,
				      int, 		keynum);

int		sm_enq_skey 	HARG2(SM_SOFTKEY, 	softkey_set,
				      CHAR *, 		key_name);

void		sm_set_skey 	HARG3(SM_SOFTKEY, 	softkey_set,
				      CHAR *, 		key_name, 
				      int, 		value);

void 		sm_set_skey_label 
				HARG4(SM_SOFTKEY, 	skey,
				      int,		key_num,
				      CHAR *,		upper,
				      CHAR *,		lower);

void 		sm_set_skey_next_skey 
				HARG2(SM_SOFTKEY, 	skey,
				      CHAR *,		next_key);

SM_SOFTKEY	*sm_first_skey	HARG1(SM_FILE,		screenset);

SM_SOFTKEY	*sm_next_skey 	HARG1(SM_SOFTKEY *, 	skey);

/*
 *
 * Menu label control and enquiry
 *
 */

SM_MENU		sm_create_menu	HARG1(SM_FILE,		screenset);

SM_MENU		*sm_destroy_menu 
				HARG1(SM_MENU *,	menu);

void 		sm_destroy_all_menus 
    				HARG1(SM_FILE, 		screenset);

SM_MENU		sm_menu_open 	HARG2(SM_FILE,		screenset,
				      CHAR *, 		menu_name);

void		sm_menu_init 	HARG1(SM_MENU, 		menu);

void		sm_paint_menu 	HARG1(SM_MENU, 		menu);

CHAR 		*sm_menu_name 	HARG1(SM_MENU, 		menu);

SM_MENU		*sm_first_menu	HARG1(SM_FILE,		screenset);

SM_MENU		*sm_next_menu 	HARG1(SM_MENU *, 	menu);

/*
 *
 * Data field control and enquiry
 *
 */

SM_FIELD	*sm_create_fld 	HARG1(SM_SCREEN, 	screen);

SM_FIELD	*sm_destroy_fld HARG1(SM_FIELD *, 	field);

void 		sm_destroy_all_flds 
				HARG1(SM_SCREEN, 	screen);

void 		sm_edit_master 	HARG1(SM_FIELD, 	detail_field);

SM_SCREEN	sm_editing_master NOARGS;

SM_FIELD	sm_detail_field	NOARGS;

void		sm_paint_fld 	HARG5(int,		window,
				      CHAR *, 		start,
				      SM_FIELD, 	field,
				      int,		enhance,
				      int,		do_base);

SM_FIELD	*sm_fld_openp 	HARG2(SM_SCREEN, 	screen,
				      CHAR *, 		field_name);

SM_FIELD	sm_fld_open 	HARG2(SM_SCREEN, 	screen,
				      CHAR *, 		field_name);

CHAR		*sm_fld_init 	HARG1(SM_FIELD, 	field);

int		sm_non_blank	HARG1(SM_FIELD,		field);

CHAR		*sm_fld_enq 	HARG1(SM_FIELD, 	field);

CHAR 		*sm_fld_get 	HARG2(SM_SCREEN, 	screen, 
				      CHAR *, 		field_name);

void		sm_fld_set 	HARG2(SM_FIELD, 	field,
				      CHAR *, 		c_value);

void		sm_fld_set_default
    				HARG2(SM_FIELD, 	field,
				      CHAR *, 		c_value);

CHAR		*sm_fld_get_default
    				HARG1(SM_FIELD, 	field);

void		sm_fld_hidden 	HARG2(SM_FIELD, 	field,
				      int, 		attribute);

void		sm_fld_prot 	HARG2(SM_FIELD, 	field,
				      int, 		attribute);

void		sm_fld_radix 	HARG3(SM_SCREEN, 	screen,
				      SM_FIELD, 	field,
				      CHAR, 		radix);

void		sm_set_separator HARG2(SM_FILE,		screenset,
				      CHAR, 		separator);

void		sm_fld_enh 	HARG3(SM_SCREEN, 	screen,
				      SM_FIELD, 	field,
				      ENH, 		enhancement);

int		sm_fld_changed 	HARG1(SM_FIELD, 	field);

SM_FIELD	*sm_first_fld_on_screen
    				HARG1(SM_SCREEN, 	screen);

SM_FIELD	*sm_next_fld_on_screen
			 	HARG2(SM_SCREEN, 	screen,
				      SM_FIELD *, 	fieldp);

SM_FIELD	*sm_prev_fld_on_screen 	
				HARG2(SM_SCREEN, 	screen,
				      SM_FIELD *, 	fieldp);

SM_FIELD	*sm_first_fld 	HARG1(SM_SCREEN, 	screen);

SM_FIELD	*sm_next_fld 	HARG1(SM_FIELD *, 	fieldp);

SM_FIELD	*sm_prev_fld 	HARG1(SM_FIELD *, 	fieldp);

void 		sm_rename_fld 	HARG2(SM_FIELD, 	field,
				      CHAR *, 		new_name);

int		sm_get_fld_len 	HARG1(SM_FIELD, 	field);

void		sm_set_fld_len 	HARG2(SM_FIELD, 	field,
				      int, 		new_length);

void		sm_set_fld_type HARG2(SM_FIELD, 	field,
				      int, 		field_type);

void		sm_set_fld_pos 	HARG3(SM_FIELD, 	field,
				      int, 		new_row,
				      int, 		new_col);

void		sm_set_fld_attr HARG4(SM_FIELD, 	field,
				      int, 		attr,
				      int, 		hidden,
				      int, 		protect);

SM_FIELD	*sm_pick_fld 	HARG3(SM_SCREEN, 	screen,
				      int, 		row,
				      int, 		col);

/*
 *
 * Background data
 *
 */

SM_BACKGROUND	sm_create_bg 	HARG1(SM_SCREEN, 	screen);

SM_BACKGROUND	*sm_destroy_bg 	HARG1(SM_BACKGROUND *, 	bg);

void 		sm_destroy_all_bgs 
				HARG1(SM_SCREEN, 	screen);

void		sm_paint_bg 	HARG2(int,		window,
				      SM_BACKGROUND, 	bg);

SM_BACKGROUND	*sm_first_bg 	HARG1(SM_SCREEN, 	screen);

SM_BACKGROUND	*sm_next_bg 	HARG1(SM_BACKGROUND *, 	bgp);


SM_BACKGROUND 	sm_pick_bg 	HARG2(SM_SCREEN, 	screen, 
				      int, 		row);

/*
 *
 * Event handling (filling in the fields).
 *
 */
void 		sm_add_field_popup_item 
				HARG2(SM_FIELD, 	field, 
				      CHAR *, 		item);

void 		sm_delete_field_popups 
				HARG1(SM_FIELD, 	field);

void 		sm_mouse_hit_on_fld HARG2(SM_FIELD, 	field, 
					  int, 		window);

CHAR		*sm_left_word 	HARG2(CHAR *, 		start,
				      CHAR *, 		pos);

CHAR		*sm_right_word 	HARG2(CHAR *, 		start,
				      CHAR *, 		pos);

int		sm_getch	NOARGS;

int		sm_destroy_callback NOARGS;

void 		sm_push_command	HARG1(int, 	command);

void		sm_add_callback HARG2(f_ptr,		lambda,
				      void *,		object);

void		sm_main_loop	NOARGS;

SM_FIELD	sm_get_field 	NOARGS;

void	 	sm_set_field 	HARG1(SM_FIELD, 	f);

int 		sm_expand_fields 
				HARG3(SM_SCREEN, 	screen, 
				      CHAR *, 		output, 
				      CHAR *, 		input);

int 		sm_transpose_words HARG2(CHAR *, 	str, 
					 CHAR *, 	pos);

int		sm_setup_fld 	HARG5(int,		window,
				      SM_FIELD, 	field,
				      int,		write_protect,
				      SM_SCREEN,	target_for_popups,
				      int,		target_col);

ARRAY		sm_set_keyword HARG4(ARRAY,	 	table, 
				     int, 		command, 
				     CHAR *, 		string, 
				     CHAR *, 		help);

int 		sm_set_command 	HARG3(int, 		command, 
				      CHAR *, 		string,
				      CHAR *,		help);

int		sm_lookup_command HARG1(CHAR *, 	string);

/*
 *
 * Utilities
 *
 */

void		sm_line_error 	HARG3(CHAR *, 		msg,
				      CHAR *, 		offense,
				      int,		line_num);

void		sm_error 	HARG1(CHAR *, 		msg);

void 		sm_file_error 	HARG3(CHAR *, 		msg, 
				      CHAR *, 		filename, 
				      int, 		error);

int		sm_confirm 	HARG1(CHAR *, 		msg);

void		sm_read_built_ins NOARGS;

int		sm_setup_prompt	HARG4(CHAR *, 		prompt,
				      CHAR *,		prompt2,
				      CHAR *, 		result_default,
				      SM_SOFTKEY,	skey);

CHAR		*sm_get_prompt_value NOARGS;

void		sm_message 	HARG1(CHAR *, 		msg);

void		sm_bell 	NOARGS;

SM_DATA		sm_increase_size HARG2(SM_DATA, 	array,
				       INDEX *, 		count);

void		sm_delete_data 	HARG1(SM_DATA, 		data);

CHAR		*sm_parse 	HARG3(CHAR *, 		line,
				      int, 		max_length,
				      CHAR, 		separator);

CHAR 		*sm_trim 	HARG1(CHAR *, 		line);

CHAR		*sm_nextfield 	HARG4(int,		separator,
				      CHAR *, 		line,
				      CHAR *, 		sep,
				      int, 		max_length);

void		sm_toupper 	HARG1(CHAR *, 		p);

void		sm_tolower 	HARG1(CHAR *, 		p);

int		sm_fix_name 	HARG1(CHAR *, 		p);

CHAR		*sm_assign 	HARG3(CHAR *, 		to,
				      CHAR *, 		from,
				      int, 		max_length);

void 		sm_setup_selection
				HARG7(SM_SCREEN,	screen,
				      INDEX *, 		index,
				      int, 		row,
				      int, 		col,
				      f_ptr, 		helper,
				      void *,		helperdata,
				      SM_SOFTKEY,	skey);

f_ptr 		_sm_get_field_trigger
    				HARG1(SM_FIELD, 	field);

f_ptr 		sm_get_field_trigger
    				HARG1(SM_FIELD, 	field);

f_ptr 		sm_edit_get_field_trigger
    				HARG1(SM_FIELD, 	field);

/*
 *
 * Data storage routines
 *
 */

void smdb_remove_funnies
			HARG3(CHAR *,		out, 
			      CHAR *, 		in, 
			      int, 		untabify);

int smdb_read_file 	HARG3(CHAR *, 		filename, 
			      SM_SCREEN, 	screen,
			      int,		untabify);

int smdb_write_file 	HARG3(CHAR *, 		filename, 
			      SM_SCREEN, 	screen,
			      int,		emergency);

CHAR *smdb_read_next 	HARG1(SM_SCREEN, 	screen);

CHAR *smdb_read_prev 	HARG1(SM_SCREEN, 	screen);

CHAR *smdb_get_current 	HARG1(SM_SCREEN, 	screen);

int smdb_set_current 	HARG2(SM_SCREEN, 	screen, 
			      CHAR *, 		new_record);

CHAR *smdb_seek 	HARG2(SM_SCREEN, 	screen, 
			      INDEX, 		index);

int smdb_write 		HARG2(SM_SCREEN, 	screen, 
			      CHAR *, 		new_record);

int smdb_insert_rec 	HARG2(SM_SCREEN, 	screen, 
			      CHAR *, 		new_record);

int smdb_delete_rec 	HARG1(SM_SCREEN, 	screen);

void smdb_delete_data 	HARG1(SM_SCREEN, 	screen);

INDEX smdb_num_records HARG1(SM_SCREEN, 	screen);

INDEX smdb_enq_position
			HARG1(SM_SCREEN, 	screen);

int smdb_file_changed 	HARG1(SM_SCREEN, 	screen);

void smdb_set_file_unchanged HARG1(SM_SCREEN, 	screen);

void smdb_set_file_changed HARG1(SM_SCREEN, 	screen);

int smdb_sort_data 	HARG2(ARRAY, 		data, 
			      SM_SORTKEY *, 	sortkey);

void sm_mktemp 		HARG2(CHAR *, 		filename, 
			      CHAR *, 		pattern);

void sm_error_exit	HARG1(CHAR *, 		msg);

#endif /* SMLIB */

/* For emacs:
 * Local Variables:
 * tab-width: 8
 * End:
 */
